﻿using System;
using System.Collections.Generic;

namespace Enferno.Public.Web.Models
{
    public abstract class CheckoutModelBase :
        CheckoutBaseModelBase
            <BasketModel, BasketItemModel, PromotionModel, OnHandStatusModel, PriceModel, ProductFileModel,
                CheckoutBuyerModel, DeliveryMethodModel, PaymentMethodModel, PaymentServiceModel, AddressModel>
    {
        
    }

    public abstract class CheckoutBaseModelBase<
        TBasketModel, 
        TBasketItemModel, 
        TPromotionModel, 
        TOnHandStatusModel, 
        TPriceModel, 
        TProductFileModel, 
        TCheckoutBuyerModel, 
        TDeliveryMethodModel, 
        TPaymentMethodModel,
        TPaymentServiceModel,
        TAddressModel>
        where TBasketModel: BasketBaseModel<TBasketItemModel, TPromotionModel, TOnHandStatusModel, TPriceModel, TProductFileModel>
        where TBasketItemModel: BasketItemBaseModel<TPriceModel>
        where TPromotionModel: PromotionBaseModel<TProductFileModel>
        where TOnHandStatusModel: OnHandStatusModel
        where TPriceModel: PriceModel
        where TProductFileModel: ProductFileModel
        where TCheckoutBuyerModel: CheckoutBuyerModel
        where TDeliveryMethodModel: DeliveryMethodModel
        where TPaymentMethodModel: PaymentMethodBaseModel<TPaymentServiceModel>
        where TPaymentServiceModel: PaymentServiceModel
        where TAddressModel: AddressModel
    {
        public TBasketModel Basket { get; set; }
        public TCheckoutBuyerModel Buyer { get; set; }
        public ICheckoutPayerModel<TAddressModel> Payer { get; set; }
        public ICheckoutShipToModel<TAddressModel> ShipTo { get; set; }
        public IEnumerable<TDeliveryMethodModel> DeliveryMethods { get; set; }
        public IEnumerable<TPaymentMethodModel> PaymentMethods { get; set; }
        public string OrderReference { get; set; }
    }

    public class CheckoutModel<
        TPayer, 
        TShipTo, 
        TBasketModel,
        TBasketItemModel,
        TPromotionModel,
        TOnHandStatusModel,
        TPriceModel,
        TProductFileModel,
        TCheckoutBuyerModel,
        TDeliveryMethodModel,
        TPaymentMethodModel,
        TPaymentServiceModel,
        TAddressModel> : CheckoutBaseModelBase<
                TBasketModel, 
                TBasketItemModel, 
                TPromotionModel, 
                TOnHandStatusModel, 
                TPriceModel, 
                TProductFileModel, 
                TCheckoutBuyerModel, 
                TDeliveryMethodModel, 
                TPaymentMethodModel, 
                TPaymentServiceModel,
                TAddressModel>
        where TBasketModel : BasketBaseModel<TBasketItemModel, TPromotionModel, TOnHandStatusModel, TPriceModel, TProductFileModel>
        where TBasketItemModel : BasketItemBaseModel<TPriceModel>
        where TPromotionModel : PromotionBaseModel<TProductFileModel>
        where TOnHandStatusModel : OnHandStatusModel
        where TPriceModel : PriceModel
        where TProductFileModel : ProductFileModel
        where TCheckoutBuyerModel : CheckoutBuyerModel
        where TDeliveryMethodModel : DeliveryMethodModel
        where TPaymentMethodModel : PaymentMethodBaseModel<TPaymentServiceModel>
        where TPaymentServiceModel : PaymentServiceModel
        where TPayer : ICheckoutPayerModel<TAddressModel>
        where TShipTo : ICheckoutShipToModel<TAddressModel>
        where TAddressModel: AddressModel
    {
        public new TPayer Payer { get; set; }
        public new TShipTo ShipTo { get; set; }
    }

    public class CompanyCheckoutModel :
        CompanyCheckoutBaseModel
            <CheckoutCompanyPayerModel, CheckoutCompanyShipToModel, CheckoutBuyerModel, BasketModel, BasketItemModel, PromotionModel, OnHandStatusModel, PriceModel, ProductFileModel,
                DeliveryMethodModel, PaymentMethodModel, PaymentServiceModel, CompanyInformationModel, AddressModel>
    {
        
    }

    public class CompanyCheckoutBaseModel<
        TCheckoutCompanyPayerModel,
        TCheckoutCompanyShipToModel,
        TCheckoutBuyerModel,
        TBasketModel,
        TBasketItemModel,
        TPromotionModel,
        TOnHandStatusModel,
        TPriceModel,
        TProductFileModel,
        TDeliveryMethodModel,
        TPaymentMethodModel,
        TPaymentServiceModel,
        TCompanyInformationModel,
        TAddressModel> : CheckoutModel<TCheckoutCompanyPayerModel, TCheckoutCompanyShipToModel, TBasketModel, TBasketItemModel, TPromotionModel, TOnHandStatusModel, TPriceModel, TProductFileModel, TCheckoutBuyerModel, TDeliveryMethodModel, TPaymentMethodModel, TPaymentServiceModel, TAddressModel>
        where TCheckoutCompanyPayerModel: CheckoutCompanyPayerBaseModel<TCompanyInformationModel, TAddressModel>
        where TCheckoutCompanyShipToModel: CheckoutCompanyShipToBaseModel<TCompanyInformationModel, TAddressModel>
        where TCheckoutBuyerModel : CheckoutBuyerModel
        where TBasketModel : BasketBaseModel<TBasketItemModel, TPromotionModel, TOnHandStatusModel, TPriceModel, TProductFileModel>
        where TBasketItemModel : BasketItemBaseModel<TPriceModel>
        where TPromotionModel : PromotionBaseModel<TProductFileModel>
        where TOnHandStatusModel : OnHandStatusModel
        where TPriceModel : PriceModel
        where TProductFileModel : ProductFileModel
        where TDeliveryMethodModel : DeliveryMethodModel
        where TPaymentMethodModel : PaymentMethodBaseModel<TPaymentServiceModel>
        where TPaymentServiceModel : PaymentServiceModel
        where TCompanyInformationModel: CompanyInformationModel
        where TAddressModel: AddressModel
    {
        
    }

    public class PrivateCheckoutModel :
    PrivateCheckoutBaseModel
        <CheckoutPrivatePayerModel, CheckoutPrivateShipToModel, CheckoutBuyerModel, BasketModel, BasketItemModel, PromotionModel, OnHandStatusModel, PriceModel, ProductFileModel,
            DeliveryMethodModel, PaymentMethodModel, PaymentServiceModel, PersonInformationModel, AddressModel>
    {

    }

    public class PrivateCheckoutBaseModel<
        TCheckoutPrivatePayerModel,
        TCheckoutPrivateShipToModel,
        TCheckoutBuyerModel,
        TBasketModel,
        TBasketItemModel,
        TPromotionModel,
        TOnHandStatusModel,
        TPriceModel,
        TProductFileModel,
        TDeliveryMethodModel,
        TPaymentMethodModel,
        TPaymentServiceModel,
        TPersonInformationModel,
        TAddressModel> : CheckoutModel<TCheckoutPrivatePayerModel, TCheckoutPrivateShipToModel, TBasketModel, TBasketItemModel, TPromotionModel, TOnHandStatusModel, TPriceModel, TProductFileModel, TCheckoutBuyerModel, TDeliveryMethodModel, TPaymentMethodModel, TPaymentServiceModel, TAddressModel>
        where TCheckoutPrivatePayerModel: CheckoutPrivatePayerBaseModel<TPersonInformationModel, TAddressModel>
        where TCheckoutPrivateShipToModel : CheckoutPrivateShipToBaseModel<TPersonInformationModel, TAddressModel>
        where TCheckoutBuyerModel : CheckoutBuyerModel
        where TBasketModel : BasketBaseModel<TBasketItemModel, TPromotionModel, TOnHandStatusModel, TPriceModel, TProductFileModel>
        where TBasketItemModel : BasketItemBaseModel<TPriceModel>
        where TPromotionModel : PromotionBaseModel<TProductFileModel>
        where TOnHandStatusModel : OnHandStatusModel
        where TPriceModel : PriceModel
        where TProductFileModel : ProductFileModel
        where TDeliveryMethodModel : DeliveryMethodModel
        where TPaymentMethodModel : PaymentMethodBaseModel<TPaymentServiceModel>
        where TPaymentServiceModel : PaymentServiceModel
        where TPersonInformationModel: PersonInformationModel
        where TAddressModel: AddressModel
    {
        
    }
}
